package com.mixed.mixedserver.game.network;

import com.mixed.mixedserver.game.entity.GameMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * WebSocket 游戏消息编码器
 * 将 GameMessage 编码为 WebSocket 二进制帧格式
 */
public class WebSocketGameMessageEncoder extends ChannelOutboundHandlerAdapter {
    
    private static final Logger logger = LoggerFactory.getLogger(WebSocketGameMessageEncoder.class);
    
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof GameMessage) {
            GameMessage gameMessage = (GameMessage) msg;
            
            try {
                // 使用 MessagePack 序列化消息
                byte[] messageData = encodeToMessagePack(gameMessage);
                
                // 创建带长度前缀的数据
                ByteBuf buffer = Unpooled.buffer(4 + messageData.length);
                buffer.writeInt(messageData.length); // 4字节长度前缀
                buffer.writeBytes(messageData);     // 消息数据
                
                // 创建 WebSocket 二进制帧
                BinaryWebSocketFrame frame = new BinaryWebSocketFrame(buffer);
                
                // 发送帧
                ctx.write(frame, promise);
                
            } catch (Exception e) {
                logger.error("Error encoding GameMessage to WebSocket frame", e);
                promise.setFailure(e);
            }
        } else {
            // 非 GameMessage 对象直接传递
            ctx.write(msg, promise);
        }
    }
    
    /**
     * 将 GameMessage 编码为 MessagePack 格式
     */
    private byte[] encodeToMessagePack(GameMessage gameMessage) throws Exception {
        MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
        
        // 创建消息对象
        packer.packMapHeader(3); // type, playerId, data
        
        // 消息类型
        packer.packString("type");
        packer.packString(gameMessage.getType().name());
        
        // 玩家ID
        packer.packString("playerId");
        if (gameMessage.getPlayerId() != null) {
            packer.packString(gameMessage.getPlayerId());
        } else {
            packer.packNil();
        }
        
        // 消息数据
        packer.packString("data");
        if (gameMessage.getData() != null) {
            packData(packer, gameMessage.getData());
        } else {
            packer.packNil();
        }
        
        byte[] result = packer.toByteArray();
        packer.close();
        
        return result;
    }
    
    /**
     * 根据数据类型进行 MessagePack 编码
     */
    private void packData(MessageBufferPacker packer, Object data) throws Exception {
        if (data == null) {
            packer.packNil();
        } else if (data instanceof String) {
            packer.packString((String) data);
        } else if (data instanceof Integer) {
            packer.packInt((Integer) data);
        } else if (data instanceof Long) {
            packer.packLong((Long) data);
        } else if (data instanceof Float) {
            packer.packFloat((Float) data);
        } else if (data instanceof Double) {
            packer.packDouble((Double) data);
        } else if (data instanceof Boolean) {
            packer.packBoolean((Boolean) data);
        } else if (data instanceof GameMessage.PlayerData) {
            packPlayerData(packer, (GameMessage.PlayerData) data);
        } else if (data instanceof GameMessage.Position) {
            packPosition(packer, (GameMessage.Position) data);
        } else if (data instanceof GameMessage.Rotation) {
            packRotation(packer, (GameMessage.Rotation) data);
        } else {
            // 对于未知类型，尝试转换为字符串
            packer.packString(data.toString());
        }
    }
    
    private void packPlayerData(MessageBufferPacker packer, GameMessage.PlayerData data) throws Exception {
        packer.packMapHeader(5);
        
        packer.packString("position");
        if (data.getPosition() != null) {
            packPosition(packer, data.getPosition());
        } else {
            packer.packNil();
        }
        
        packer.packString("rotation");
        if (data.getRotation() != null) {
            packRotation(packer, data.getRotation());
        } else {
            packer.packNil();
        }
        
        packer.packString("velocity");
        if (data.getVelocity() != null) {
            packPosition(packer, data.getVelocity());
        } else {
            packer.packNil();
        }
        
        packer.packString("health");
        packer.packFloat(data.getHealth());
        
        packer.packString("name");
        if (data.getName() != null) {
            packer.packString(data.getName());
        } else {
            packer.packNil();
        }
    }
    
    private void packPosition(MessageBufferPacker packer, GameMessage.Position data) throws Exception {
        packer.packMapHeader(3);
        
        packer.packString("x");
        packer.packFloat(data.getX());
        
        packer.packString("y");
        packer.packFloat(data.getY());
        
        packer.packString("z");
        packer.packFloat(data.getZ());
    }
    
    private void packRotation(MessageBufferPacker packer, GameMessage.Rotation data) throws Exception {
        packer.packMapHeader(4);
        
        packer.packString("x");
        packer.packFloat(data.getX());
        
        packer.packString("y");
        packer.packFloat(data.getY());
        
        packer.packString("z");
        packer.packFloat(data.getZ());
        
        packer.packString("w");
        packer.packFloat(data.getW());
    }
}